package ru.compft.common.utils;

import org.jfree.chart.ChartFactory;
import org.jfree.chart.ChartUtilities;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.axis.CategoryAxis;
import org.jfree.chart.axis.CategoryLabelPositions;
import org.jfree.chart.plot.CategoryPlot;
import org.jfree.chart.plot.PiePlot;
import org.jfree.chart.plot.PiePlot3D;
import org.jfree.chart.plot.PlotOrientation;
import org.jfree.data.category.CategoryDataset;
import org.jfree.data.category.DefaultCategoryDataset;
import org.jfree.data.general.DefaultPieDataset;
import org.jfree.data.general.PieDataset;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.CollectionUtils;

import java.awt.*;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;

/**
 * Created with IntelliJ IDEA.
 * User: VVasiliev
 * Date: 06.11.12
 * Time: 12:27
 * Утилиты для библиотеки JFreeChart
 * Методы реализуют стандартный функционал по созданию диаграмм
 */
public class JFreeChartUtils {
    private static final Logger logger = LoggerFactory.getLogger(JFreeChartUtils.class);

    /**
     * Создание Pie DataSet из файла
     */
    public static PieDataset createPieDataSetFromFile(File dataFile) throws IOException {
        final Map<String, Double> dataMap = new HashMap<String, Double>();
        final BufferedReader bReader = new BufferedReader(new FileReader(dataFile));
        String s;
        while ((s = bReader.readLine()) != null) {
            String datavalue[] = s.split("=");
            String category = datavalue[0];
            String value = datavalue[1];
            dataMap.put(category, Double.parseDouble(value));
        }
        bReader.close();

        return createPieDataSetFromMap(dataMap);
    }

    /**
     * Создание Pie DataSet из Map<String, Double></>
     */
    public static PieDataset createPieDataSetFromMap(Map<String, Double> dataMap) throws IOException {
        final DefaultPieDataset pieDataset = new DefaultPieDataset();

        if (!CollectionUtils.isEmpty(dataMap)) {
            final Set<Map.Entry<String, Double>> entrySet = dataMap.entrySet();
            for (Map.Entry<String, Double> entry : entrySet) {
                final String category = entry.getKey();
                final Double value = entry.getValue();

                pieDataset.setValue(category, value);
            }
        }

        return pieDataset;
    }

    /**
     * Создание Category DataSet из List<String>
     * Список должен быть в виде массива строк [Серия,Категория,Значение]
     */
    public static CategoryDataset createCategoryDatasetFromList(java.util.List<String[]> dataList) throws IOException {
        return addDataToCategoryDatasetFromList(new DefaultCategoryDataset(), dataList);
    }

    /**
     * Добавление данных в существующую Category DataSet из List<String>
     * Список должен быть в виде массива строк [Серия,Категория,Значение]
     */
    public static CategoryDataset addDataToCategoryDatasetFromList(DefaultCategoryDataset categoryDataset, java.util.List<String[]> dataList) throws IOException {
        if (categoryDataset != null && !CollectionUtils.isEmpty(dataList)) {
            for (String[] dataString : dataList) {
                if (dataString != null && dataString.length == 3) {
                    final String series = dataString[0];
                    final String category = dataString[1];
                    final Double value = Double.parseDouble(dataString[2]);

                    categoryDataset.addValue(value, series, category);
                }
            }
        }

        return categoryDataset;
    }

    /**
     * Создание 3D Pie Chart из PieDataset
     *
     * @param dataset
     * @return
     */
    public static JFreeChart create3DPieChart(String title, PieDataset dataset, boolean legend, boolean tooltips, boolean urls) {
        final JFreeChart chart = ChartFactory.createPieChart3D(title, dataset, legend, tooltips, urls);

        final PiePlot3D p = (PiePlot3D) chart.getPlot();
        p.setForegroundAlpha(0.5f);
        p.setBackgroundAlpha(0.2f);

        chart.setBackgroundPaint(Color.white);
        chart.setAntiAlias(true);
        chart.setBorderVisible(false);
        chart.setTextAntiAlias(true);

        return chart;
    }

    /**
     * Создание 3D Pie Chart из PieDataset
     *
     * @param dataset
     * @return
     */
    public static JFreeChart createPieChart(String title, PieDataset dataset, boolean legend, boolean tooltips, boolean urls) {
        final JFreeChart chart = ChartFactory.createPieChart(title, dataset, legend, tooltips, urls);

        final PiePlot p = (PiePlot) chart.getPlot();
        p.setBackgroundAlpha(0.2f);

        chart.setBackgroundPaint(Color.white);
        chart.setAntiAlias(true);
        chart.setBorderVisible(false);
        chart.setTextAntiAlias(true);

        return chart;
    }

    /**
     * Создание Bar Chart из CategoryDataset
     * Будет простая диаграмма
     *
     * @param title
     * @param dataset
     * @param orientation
     * @param categoryAxisName
     * @param valueAxisName
     * @return
     */
    public static JFreeChart createBarChart(String title, CategoryDataset dataset, PlotOrientation orientation, String categoryAxisName,
                                            String valueAxisName, boolean legend, boolean tooltips, boolean urls) {
        final JFreeChart chart = ChartFactory.createBarChart(title, categoryAxisName, valueAxisName, dataset, orientation, legend, tooltips, urls);

        final CategoryPlot p = (CategoryPlot) chart.getPlot();
        p.setBackgroundAlpha(0.2f);

        // Название категорий (ось Х) будеи смещено виниз на 45 градусов
        final CategoryAxis domainAxis = p.getDomainAxis();
        domainAxis.setCategoryLabelPositions(CategoryLabelPositions.DOWN_45);

        chart.setBackgroundPaint(Color.white);
        chart.setAntiAlias(true);
        chart.setBorderVisible(false);
        chart.setTextAntiAlias(true);

        return chart;
    }

    /**
     * Сохранение диаграммы в виде JPEG-файла с опредленными параметрами
     *
     * @param chart
     * @param imgFile
     */
    public static void saveChartAsJPEG(JFreeChart chart, File imgFile, int width, int height) {
        try {
            ChartUtilities.saveChartAsJPEG(imgFile, chart, width, height);
        } catch (IOException e) {
            logger.error("Problem occurred save chart as JPEG.", e);
        }
    }

    /**
     * Сохранение диаграммы в виде PNG-файла с опредленными параметрами
     *
     * @param chart
     * @param imgFile
     */
    public static void saveChartAsPNG(JFreeChart chart, File imgFile, int width, int height) {
        try {
            ChartUtilities.saveChartAsPNG(imgFile, chart, width, height);
        } catch (IOException e) {
            logger.error("Problem occurred save chart as PNG.", e);
        }
    }
}
